/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package actuatedocumentor;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;

/**
 *
 * @author Richard
 */
public class BasParser {

    private String basFile;
    private ArrayList globals;
    private OrderedHashMap classes;
    private ArrayList libraries;
    private ArrayList versions;
    //private HashMap superclasses;
    
    public BasParser(String filename) {
        basFile = filename;
        globals = new ArrayList();
        classes = new OrderedHashMap();
        libraries = new ArrayList();
        //superclasses = new HashMap();
        
        if(this.getVersionData()==false){
            versions = new ArrayList();
        }
        
        
    }

    public void parseFile() {
        
        String currentClass = "";
        
        try {
            //use buffering, reading one line at a time
      //FileReader always assumes default encoding is OK!
            File infile = new File(basFile);
         
            
            FileInputStream input = new FileInputStream(infile);
            InputStreamReader inputfilereader = new InputStreamReader(input, "UTF-16");
            BufferedReader br = new BufferedReader(inputfilereader);
            
            try {
                String line = null; //not declared within while loop
        /*
        * readLine is a bit quirky :
        * it returns the content of a line MINUS the newline.
        * it returns null only for the END of the stream.
        * it returns an empty String if two newlines appear in a row.
        */
                while ((line = br.readLine()) != null) { //
                    
                    if(line.indexOf("' Modules generated")>-1){
                        setLibraries(br);
                    }
                    
                    if(line.indexOf("' Global variables")>-1){
                        setGlobals(br);
                    }
                    
                    if(line.indexOf("#Location \"")>-1){
                        String className = line.substring(line.lastIndexOf("::")+2);
                        
                        if(className.indexOf("%")>-1){
                            String classIdentifier = line.substring(0, line.indexOf("%") );
                            //String objectIdentifier = line.substring(0, ((MethodDetails)ar.get(i)).getMethodName()  );
                            className  = className.substring(0, className.indexOf("%") );
                            
                            setClasses(br, className, classIdentifier, currentClass.substring(currentClass.lastIndexOf(",")+1));
                        }
                        
                    }
                    
                    if(line.indexOf("Class ")>-1&&line.indexOf("Subclass Of")>-1){
                        currentClass = currentClass+","+line.substring(line.indexOf("Subclass ")+12);
                        
                    }
                    
                    if(line.indexOf("End Class ")>-1){
                        currentClass = currentClass.substring(0,currentClass.lastIndexOf(",")-1);
                        
                        
                    }
                    
                    
                    
                }
                
                ReportVersion rv = new ReportVersion(versions.size()+1,this.globals, this.classes, this.libraries);//, this.superclasses);
                    
                    if(this.differentVersion(rv)==true){
                        //check for changes
                        VersionChange vc = new VersionChange();
                        if(versions.size()-1==-1){
                            vc.doChecks(rv, null);
                        
                        }else{
                            vc.doChecks(rv, (ReportVersion)versions.get(versions.size()-1));
                        
                        }
                        
                        rv.setClassAdded(vc.getClassAdded());
                        rv.setClassChangeMethodAdded(vc.getClassChangeMethodAdded());
                        rv.setClassChangeMethodChanged(vc.getClassChangeMethodChanged());
                        rv.setClassChangeMethodRemoved(vc.getClassChangeMethodRemoved());
                        rv.setClassRemoved(vc.getClassRemoved());
                        
                        versions.add(rv);
                    }
            } finally {
                input.close();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    
    public void printChanges(){
        //for(int i = 0; i<versions.size();i++){
            System.out.println(((ReportVersion)versions.get((versions.size()-1))).showChanges());
          //  System.out.println(((ReportVersion)versions.get(i)).showChanges());
        //}    
    }
    
    
    
    private ActuateClass classExists(String classIdentifier){
        
        if(classes.containsKey(classIdentifier)){
            return (ActuateClass)classes.get(classIdentifier);
        }
        
        return null;
    }
    
    
    private void setLibraries(BufferedReader input){
         
        
        try {
                String line = null; //not declared within while loop
        /*
        * readLine is a bit quirky :
        * it returns the content of a line MINUS the newline.
        * it returns null only for the END of the stream.
        * it returns an empty String if two newlines appear in a row.
        */
                while ((line = input.readLine()) != null&&line.indexOf("'---")==-1) {
                    if(line.indexOf("Includes ")>0){
                        
                        line = line.substring(line.indexOf("Includes ")+9);
                        libraries.add(line.substring(line.lastIndexOf("/")+1));
                        
                    }
                    
                }
            } catch (IOException ex) {
            ex.printStackTrace();
        } 
        
                
                
    }
    
    private boolean differentVersion(ReportVersion rv){
        if(versions.size()>0){
            ReportVersion rvLast = (ReportVersion)versions.get(versions.size()-1);
            if(rvLast.getCompareString().compareTo(rv.getCompareString())==0){
                System.out.println("Same as old version");
                return false;
            }
        }
        
        System.out.println("New version");
        return true; 
    }
    
    public void printVersionData(){
        System.out.println("Number of versions = "+versions.size());
        for (int i = 0; i<versions.size();i++){
            
            System.out.println(versions.get(i).toString());
        }
    }
    
    
    private void setClasses(BufferedReader input, String className, String classIdentifier, String superclassname){
        boolean exists = false;
        ActuateClass ao;
        
        if(classExists(classIdentifier)!=null){
            ao = classExists(classIdentifier);
            exists = true;
        }else{
            
            ao = new ActuateClass(className,classIdentifier, superclassname);
        
        }
            
        
        try {
                String line = null; //not declared within while loop
        /*
        * readLine is a bit quirky :
        * it returns the content of a line MINUS the newline.
        * it returns null only for the END of the stream.
        * it returns an empty String if two newlines appear in a row.
        */
                String code = "";
                String methodName = "";
                while ((line = input.readLine()) != null&&line.indexOf("#Pop")<0) {
                        if(line.indexOf("Function ")>-1&&line.indexOf("End Function")<0){
                            methodName = line.substring(line.indexOf("Function ")+9, line.indexOf("("));
                        }else if(line.indexOf("Sub ")>-1&&line.indexOf("End Sub")<0){
                            methodName = line.substring(line.indexOf("Sub ")+4, line.indexOf("("));
                        }
                        code = code + "\n\r" + line;
                        
                    }
                
                ao.addMethod(methodName,code);
                if(exists==false){
                classes.put(ao.getClassIdentifier(), ao);
                }
                    
            } catch (IOException ex) {
            ex.printStackTrace();
        } 
        
        
    }
    

    private void setGlobals(BufferedReader input){
        try {
                String line = null; //not declared within while loop
        /*
        * readLine is a bit quirky :
        * it returns the content of a line MINUS the newline.
        * it returns null only for the END of the stream.
        * it returns an empty String if two newlines appear in a row.
        */
                while ((line = input.readLine()) != null&&line.indexOf("End Declare")<0) {
                    if(line.indexOf("Global")>0&& line.indexOf("As")>0){
                        
                        line = line.substring(line.indexOf("Global")+7);
                        String name = line.substring(0,line.indexOf(" "));
                        String type = line.substring(line.indexOf("As")+2);
                        type = type.replaceAll(" ", "");
                        name = name.replaceAll(" ", "");
                        GlobalVariable gv = new GlobalVariable(name,type);      
                        globals.add(gv);
                        //System.out.println(gv.toString());
                    }
                    
                }
            } catch (IOException ex) {
            ex.printStackTrace();
        } 
        
    }
    
    public boolean getVersionData(){
                String filename = "C:\\Users\\Richard\\Desktop\\Work Stuff\\PitpassScraper\\Formula1Results_with_excel_output_and_crosstab_totals.vers";
		
		FileInputStream fis = null;
		ObjectInputStream in = null;
		try {
			fis = new FileInputStream(filename);
			in = new ObjectInputStream(fis);
			versions = (ArrayList) in.readObject();
			in.close();
		} catch (IOException ex) {
			return false;
		} catch (ClassNotFoundException ex) {
			ex.printStackTrace();
		}
		// print out the size
		System.out.println("Number of previous versions " + versions.size());
		System.out.println();
                return true;
    }
    
    public void setVersionData(){
            String filename = "C:\\Users\\Richard\\Desktop\\Work Stuff\\PitpassScraper\\Formula1Results_with_excel_output_and_crosstab_totals.vers";
        	FileOutputStream fos = null;
		ObjectOutputStream out = null;
		try {
			fos = new FileOutputStream(filename);
			out = new ObjectOutputStream(fos);
			out.writeObject(versions);
			out.close();
			System.out.println("Object Persisted");
		} catch (IOException ex) {
			ex.printStackTrace();
		}
    }
}
